package com.zjmzxfzhl.modules.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.zjmzxfzhl.common.core.constant.SysConstants;
import com.zjmzxfzhl.common.core.exception.SysException;
import com.zjmzxfzhl.common.core.util.CommonUtil;
import com.zjmzxfzhl.modules.app.entity.*;
import com.zjmzxfzhl.modules.app.form.*;
import com.zjmzxfzhl.modules.app.service.*;
import com.zjmzxfzhl.modules.flowable.service.ProcessInstanceService;
import com.zjmzxfzhl.modules.flowable.vo.ProcessInstanceRequest;
import com.zjmzxfzhl.modules.sys.entity.SysUser;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zjmzxfzhl.common.core.base.BaseServiceImpl;
import com.zjmzxfzhl.modules.app.mapper.AppDocMapper;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.crypto.Data;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Service
 * 
 * @author 张森荣
 */
@Service
public class AppDocServiceImpl extends BaseServiceImpl<AppDocMapper, AppDoc>
        implements AppDocService {
    
    @Autowired
    private AppLogService appLogService;
    @Autowired
    private ProcessInstanceService processInstanceService;
    @Autowired
    private AppTaskService appTaskService;
    @Autowired
    private AppProjService appProjService;

    @Override
    public IPage<AppDocVo> list(IPage<AppDocVo> page, AppDocVo appDocVo) {
        return page.setRecords(baseMapper.list(page, appDocVo));
    }
    @Override
    public List<AppDocVo> getList(IPage<AppDocVo> page, AppDocVo appDocVo) {
        return baseMapper.list(page, appDocVo);
    }
    @Override
    public Integer selectRowCount(AppDocVo appDocVo) {
        return baseMapper.selectRowCount(appDocVo);
    }

    /**
     * 统计任务数量
     * @return
     */
    @Override
    public List<DocTotalVo> docTotal(AppDoc appDoc) {
        return baseMapper.docTotal(appDoc);
    }
    @Override
    public List<AppDocVo> subTaskDoc(String taskId) {
        return baseMapper.subTaskDoc(taskId);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean softDelete(String ids) {
        Boolean result = true;
        String[] idsArr = ids.split(",");

        for (String s:idsArr) {
            AppDoc appDoc=baseMapper.selectById(s);
            appDoc.setDeleted("1");
            appDoc.setDirId("###");
            appDoc.setUpdateTime(new Date());
            result= this.updateById(appDoc);
        }
        return result;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recovery(String ids,String dirId) {
        Boolean result = true;
        String[] idsArr = ids.split(",");

        for (String s:idsArr) {
            AppDoc appDoc=baseMapper.selectById(s);
            appDoc.setDeleted("0");
            appDoc.setDirId(dirId);
            appDoc.setUpdateTime(new Date());
            result= this.updateById(appDoc);
        }
        return result;
    }
    /**
     * 新增项目，自动计算机构级别、机构级次码、是否叶子
     *
     * @param appDoc
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAppDoc(AppDoc appDoc) {
        //添加项目
        appDoc =setAppDoc(appDoc);
        Boolean result = true;
        //判断是否需要拆分文档true时不拆分多个文档
        Boolean bool=false;
        if("02".equals(appDoc.getDocType())||"05".equals(appDoc.getDocType())){
            bool=true;
        }
        if("02".equals(appDoc.getDocType())){
            if("01".equals(appDoc.getDocSubtype())||"02".equals(appDoc.getDocSubtype())||"03".equals(appDoc.getDocSubtype())){
                bool=false;
            }
        }

        if(bool){
            result = this.save(appDoc);
            if(result==false){
                return false;
            }
            appDoc =this.getById(appDoc.getDocId());
            appLogService.addLog("新增文档："+appDoc.getName(),"04",appDoc.getDocId());
        }else{
            for (DocFilePath addFilePath:appDoc.getDocFilePath()) {
                List<DocFilePath> addFilePathList=new ArrayList<>();
                addFilePathList.add(addFilePath);
                AppDoc addAppDoc=new AppDoc();
                BeanUtils.copyProperties(appDoc,addAppDoc);
                addAppDoc.setDocFilePath(addFilePathList);
                //查找同名文件
                addAppDoc.setName(addFilePath.getFileName());
                addAppDoc=nameCheck(addAppDoc,addFilePath,1);
                //保存
                result = this.save(addAppDoc);
                if(result==false){
                    return false;
                }
                addAppDoc =this.getById(addAppDoc.getDocId());
                appLogService.addLog("新增文档："+addAppDoc.getName(),"04",addAppDoc.getDocId());
            }
        }
        return result;
    }

    private AppDoc setAppDoc(AppDoc appDoc){
        if(appDoc.getStatus()==null){
            appDoc.setStatus("00");
        }
        if(appDoc.getDirId()==null||"".equals(appDoc.getDirId())){
            appDoc.setDirId("");
        }
        appDoc.setDeleted("0");
        //文档类型为07、08：任务时置空dirId
        if("07".equals(appDoc.getDocType())||"08".equals(appDoc.getDocType())){
            appDoc.setDirId("##");
        }
        //任务附件时放入项目目录中
        if ("01".equals(appDoc.getDocType())) {
            AppTask appTask = appTaskService.queryById(appDoc.getDocTypeId());
            if (appTask.getProjId() != null && !"".equals(appTask.getProjId())) {
                AppProj appProj = appProjService.queryById(appTask.getProjId());
                appDoc.setDirId(appProj.getDirId());
            }else {//为绑定项目时无目录
                appDoc.setDirId("##");
            }
        }
        return appDoc;
    }

    //检测文件重名
    private AppDoc nameCheck(AppDoc appDoc,DocFilePath addFilePath,Integer num){
        //查找同名文件
        Map<SFunction<AppDoc,?>,Object> params=new HashMap<>();
        params.put(AppDoc::getName, appDoc.getName());
        if("07".equals(appDoc.getDocType())||"08".equals(appDoc.getDocType())){
            params.put(AppDoc::getDocTypeId, appDoc.getDocTypeId());
        }else{
            params.put(AppDoc::getDirId, appDoc.getDirId());
        }
        Integer total=this.count(new LambdaQueryWrapper<AppDoc>().allEq(params));
        if(addFilePath.getFileName()==null){
            SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
            addFilePath.setFileName(sdf.format(new Date()));
        }
        if(total>=1){
            String fileName=addFilePath.getFileName();
            if(fileName.indexOf(".")!=-1) {
                fileName=fileName.substring(0, fileName.lastIndexOf("."))+"("+num+")"+fileName.substring(fileName.lastIndexOf("."));
            }else{
                fileName=addFilePath.getFileName()+"("+num+")";
            }
            appDoc.setName(fileName);
            num++;
            appDoc =nameCheck(appDoc,addFilePath,num);
        }
        return appDoc;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppDocVo queryById(String id) {
        AppDocVo appDocVo=new AppDocVo();
        appDocVo.setDocId(id);
        List<AppDocVo> appDocVoList= baseMapper.list(null, appDocVo);
        if(appDocVoList.size()>0){
            AppDocVo result=appDocVoList.get(0);
            if ("05".equals(result.getDocType())) {
                if (result.getEndDate() != null) {
                    //过期且状态不为已过期
                    if (new Date().getTime() > result.getEndDate().getTime() && !"06".equals(result.getStatus())) {
                        timeout(result.getDocId());
                        result=this.queryById(result.getDocId());
                    }
                }

            }
            return result;
        }
        return null;
    }

    /**
     * 新增机构，自动计算机构级别、机构级次码、是否叶子
     *
     * @param appDoc
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAppDoc(AppDoc appDoc) {
        //修改任务
        AppDoc doc=this.queryById(appDoc.getDocId());
        if(!doc.getName().equals(appDoc.getName())){

            appLogService.addLog("变更文档 "+doc.getName()+" 更改标题为 "+appDoc.getName(),"04",appDoc.getDocId());
        }
        if(!doc.getFilePath().equals(appDoc.getFilePath())){

            appLogService.addLog("变更文档附件","04",appDoc.getDocId());
        }
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);
        if(result==false){
            return false;
        }

        //添加任务操作记录
        appLogService.addLog("变更文档内容","04",appDoc.getDocId());
        return result;
    }

    /**
     * 已上传
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean uploaded(String docId) {
        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        appDoc.setStatus("00");
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);

        appLogService.addLog("变更文档状态为 已上传","04",appDoc.getDocId());
        return result;
    }

    /**
     * 待审批
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pendingTrial(String docId) {
        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        appDoc.setStatus("01");
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);

        appLogService.addLog("变更文档状态为 待审批","04",appDoc.getDocId());
        return result;
    }

    /**
     * 审批中
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean inReview(String docId) {
        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        appDoc.setStatus("02");
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);

        appLogService.addLog("变更文档状态为 审批中","04",appDoc.getDocId());
        return result;
    }

    /**
     * 审批过
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reviewed(String docId) {
        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        appDoc.setStatus("04");
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);

        appLogService.addLog("变更文档状态为 审批过","04",appDoc.getDocId());
        return result;
    }

    /**
     * 已驳回
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reject(String docId) {
        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        appDoc.setStatus("05");
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);

        appLogService.addLog("变更文档状态为 已驳回","04",appDoc.getDocId());
        return result;
    }

    /**
     * 已过期
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean timeout(String docId) {
        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        appDoc.setStatus("06");
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);

        appLogService.addLog("变更文档状态为 已过期","04",appDoc.getDocId());
        return result;
    }

    /**
     * 已作废
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancel(String docId) {
        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        appDoc.setStatus("07");
        appDoc.setUpdateTime(new Date());
        Boolean result = this.updateById(appDoc);

        appLogService.addLog("变更文档状态为 已作废","04",appDoc.getDocId());
        return result;
    }

    /**
     * 启动文档审批流程实例
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean processStart(String docId) {

        AppDoc appDoc=this.getById(docId);
        if(appDoc==null){
            return false;
        }
        if(appDoc.getModelId()==null){
            throw new FlowableException("发起流程失败！检查是否存在流程！");
        }
        if("02".equals(appDoc.getStatus())||"04".equals(appDoc.getStatus())){
            throw new FlowableException("已发起过流程！");
        }
        ProcessInstanceRequest processInstanceRequest=new ProcessInstanceRequest();
        processInstanceRequest.setProcessDefinitionId(appDoc.getModelId());
        processInstanceRequest.setBusinessKey("doc:"+appDoc.getDocId());
        ProcessInstance instance = processInstanceService.start(processInstanceRequest);
        appDoc.setProcessInstanceId(instance.getProcessInstanceId());
        appDoc.setUpdateTime(new Date());
        this.updateById(appDoc);

        Boolean result=inReview(docId);

        appLogService.addLog("发起审批","04",appDoc.getDocId());
        return result;
    }

    /**
     * 查询审核文档
     *
     * @param processInstanceId
     * @return
     */
    public List<AppDocVo> procDoc(String processInstanceId) {
        return baseMapper.procDoc(processInstanceId);
    }
}
